package com.treasure.mall.zbqmallapi.aspect;

import com.treasure.mall.biz.entity.user.UserPO;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.base.ResultCodeEnum;
import com.treasure.mall.zbqmallapi.annotation.AccessControl;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 *
 * +---------------------------------------------------------
 * * @package: com.treasure.mall.zbqmallapi.aspect
 * * @author: guomw (guomwchen@foxmail.com)
 * * @date: 2020/6/12 22:47
 * * @since: V1.0.0
 * +---------------------------------------------------------
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 * Copyright 2019-2022 com.treasure.mall.zbqmallapi.aspect Inc. All rights reserved.
 */
@Component
@Aspect
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class AccessTokenAspect {
    private static final String POINT_CUT = "execution(* com.treasure.mall.zbqmallapi..*Controller.*(..))";

    @Autowired
    private SessionHandler sessionHandler;

    public AccessTokenAspect() {
        log.info(">>>>>>> {} loaded", AccessTokenAspect.class.getName());
    }

    /**
     *
     */
//    @Pointcut(POINT_CUT)
    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    private void accessTokenAspectPointCut() {
    }

    @Around("accessTokenAspectPointCut()")
    public Object token(ProceedingJoinPoint pjp) throws Throwable {
        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return pjp.proceed();
        }
        HttpServletRequest request = requestAttributes.getRequest();

        Method method = getTargetMethod(pjp);
        AccessControl accessControl = method.getAnnotation(AccessControl.class);
        if (accessControl == null) {
            accessControl = pjp.getTarget().getClass().getAnnotation(AccessControl.class);
        }
        //判断当前请求是否需要登录，如果需要，则返回未登录错误信息
        if (accessControl != null && accessControl.needLogin()) {
            UserPO user = sessionHandler.getUser(request);
            if (user == null) {
                return ApiResult.errorWith(ResultCodeEnum.NOT_LOGIN);
            }
        }
        return pjp.proceed();
    }

    public Method getTargetMethod(ProceedingJoinPoint pjp) {
        try {
            return pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), ((MethodSignature) pjp.getSignature()).getParameterTypes());
        } catch (NoSuchMethodException var2) {
            throw new IllegalStateException(var2);
        }
    }
}
